package tcdx.uap.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tcdx.uap.common.utils.Lutils;
import tcdx.uap.common.utils.MapUtils;
import tcdx.uap.mapper.FlowableMapper;
import tcdx.uap.service.entities.*;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 参数配置 服务层实现
 * 
 * @author ruoyi
 */
@Service
public class TableCRUDService {

    @Autowired
    private FlowableMapper flowableMapper;

    @Autowired
    BaseDBService baseDBService;

    public List<Integer> gen_ids(int count) {
        List<Map> l = baseDBService.selectSql("select nextval('tcdx_datatable_id_seq') id,generate_series(1, " + count + ") num");
        return l.stream().map(o -> Integer.parseInt(o.get("id").toString())).collect(Collectors.toList());
    }

    @Transactional
    public void data_mode_create(Map userInfo, Map func, Map datatable, Map<String,Object> form) {
        String table_name = (String) userInfo.get("table_name");
        List<Integer> new_ids = gen_ids(1);
        Date now = new Date();
        //单纯的插入数据到数据库
        form.put("id_", new_ids.get(0));
        //获取需要触发其他模块的字段信息
        form.put("assignee_", userInfo.get("user_name"));   //如果数据模式，则assignee_为接单人
        form.put("assignee_group_", userInfo.get("user_group"));
        form.put("complete_user_", userInfo.get("user_name"));  //如果数据模式，则complete_user_为创建人
        form.put("complete_group_", userInfo.get("user_group"));
        form.put("complete_time_", now);
        form.put("update_user_", userInfo.get("user_name"));
        form.put("update_group_", userInfo.get("user_group"));
        form.put("update_time_", now);
        form.put("form_id_", func.get("form_id"));
        baseDBService.insertMap(table_name, form);
//            datatable_update(userInfo, func, list, datatable, "data-create", now);
        ColumnRuleOperationStore columnRuleOperationStore = new ColumnRuleOperationStore();
        for(Map.Entry<String,Object> entry: form.entrySet()) {
            ColumnRuleOperation columnRuleOperation = new ColumnRuleOperation(
                    table_name,
                    entry.getKey(),
                    "user-form",
                    entry.getValue(),
                    null, null);
            columnRuleOperation.addInIds(new_ids);
            columnRuleOperationStore.addTableColumnRule(table_name, columnRuleOperation);
        }
        UserAction action = new UserAction("data-create", new Date());
        UpdateTableColumns(columnRuleOperationStore, action);

    }

    @Transactional
    public void datatable_update(Map userInfo, Map func, Map row, Map<String,Object> form, Integer id, Map datatable, String action_type, UserAction action) {
        //获取表名
        String tn = datatable.get("table_name").toString();
        Integer table_id = (Integer)datatable.get("id");
        Map<String,Object> beforeData = new HashMap();
        //横向拓展字段
        if(row==null || row.size()==0) {
            row = baseDBService.selectEq(tn, Lutils.genMap("id_", id)).get(0);
            MapUtils.copy(row, beforeData);
        }
        //系统字段，通过系统获取
        //List<Map> sysFlowFields = tableColumns.stream().filter(o-> Lutils.nvl((String)o.get("field_content_from"),"").equals("system-flow")).collect(Collectors.toList());
        //将存入log的字段
        List<Object> logIds = new ArrayList<>();
        //填充用户操作等信息
        form.put("action_type_", action_type);
        form.put("update_user_", userInfo.get("user_name"));
        form.put("update_group_", userInfo.get("user_group"));
        form.put("update_time_", action.action_time);
        form.put("form_id_", func.get("form_id"));
        baseDBService.updateIn(tn, form, "id_", Lutils.genList(id));//------------------------update database
        //添加ids
        logIds.add(id);
        //递归横向拓展 form
        ColumnRuleOperationStore columnRuleOperationStore = new ColumnRuleOperationStore();
        for(Map.Entry<String,Object> entry: form.entrySet()) {
            ColumnRuleOperation columnRuleOperation = new ColumnRuleOperation(
                    tn,
                    entry.getKey(),
                    "user-form",
                    entry.getValue(),
                    null, null);
            columnRuleOperation.addInIds(Lutils.genList(id));
            columnRuleOperationStore.addTableColumnRule(tn, columnRuleOperation);
        }
        UpdateTableColumns(columnRuleOperationStore, action);
    }

    public void UpdateTableColumns(ColumnRuleOperationStore columnRuleOperationStore, UserAction action){
        //处理下级数据
        while(true) {
            String table_name = columnRuleOperationStore.getNextTableName();
            if (table_name == null) {
                return;
            }
            //本级表
            int selfColumnRuleSize = 0;
            //自身表有没有额外追加字段，如果追加字段就要触发横向拓展
            while (selfColumnRuleSize < columnRuleOperationStore.getTableColumnSize(table_name)) {
                //判断本级表格，有没有新增规则
                selfColumnRuleSize = columnRuleOperationStore.getTableColumnSize(table_name);
                /**
                 * 一些字段由不同的表触发，不同的表触发的字段，必然独立，不关联
                 * */
                /** 根据变动的列，找到这些列触发变动的字段 -------针对本级表*/
                // updateColumns是本次表单中变动的列
                List<String> updateColumns = columnRuleOperationStore.getOperationList(table_name).stream().map(o -> o.column).collect(Collectors.toList());
                /** 根据变动的列，取触发自身表其他字段的列 ----TableColumnRelation，保存着变动列依赖的字段 */
                List<TableColumnRelation> selfDependRelation = TableColumnRelationList.getInstance(flowableMapper).getTriggerThisTableRelation(table_name, updateColumns);
                // 先锁定依赖表的ids，根据行信息获取上级表的待更新的ids
                for (TableColumnRelation relation : selfDependRelation) {
                    // 中止条件，如果该列已出现，则跳过。
                    if (updateColumns.contains(relation.update_column))
                        continue;
                    // 创建新规则
                    ColumnRuleOperation thisColumnOperation = new ColumnRuleOperation(
                            relation.table_name,
                            relation.update_column,
                            relation.update_type, null, relation, relation.depend_table_name);
                    //合并所有的变动的列的ids,先锁定依赖表的行ids，通过该条件的match字段，
                    addDependIds_FromDependColumnOperations(thisColumnOperation,
                            columnRuleOperationStore.getOperationList(thisColumnOperation.dependTableName));
                    /** 获取inIds，即匹配字段旧值的条件 */
                    addInIds_ByDependMatchColValues(thisColumnOperation);
                    columnRuleOperationStore.addTableColumnRule(thisColumnOperation.tableName, thisColumnOperation);
                }
            }
            //触发上级的操作
            List<String> updateColumns = columnRuleOperationStore.getOperationList(table_name).stream().map(o -> o.column).collect(Collectors.toList());
            List<TableColumnRelation> upperDependRelation = TableColumnRelationList.getInstance(flowableMapper).getTriggerUpperTableRelation(table_name, updateColumns);
            // 根据变动的列，取触发上级表触发更新的列 ----
            // 先锁定依赖表的ids，根据行信息获取上级表的待更新的ids
            for (TableColumnRelation upperRelation : upperDependRelation) {
                // 创建新规则
                ColumnRuleOperation upperTableColumnOperation = new ColumnRuleOperation(
                        upperRelation.table_name,
                        upperRelation.update_column,
                        upperRelation.update_type, null, upperRelation, upperRelation.depend_table_name);
                /** 获取依赖表的Ids，锁定这些ids，用于后期这些ids对应的行，修改前后的值，获取更新表的ids，即依赖更新的范围 */
                addDependIds_FromDependColumnOperations(upperTableColumnOperation,
                        columnRuleOperationStore.getOperationList(upperTableColumnOperation.dependTableName));
                /** 获取Upper表的inIds，此时匹配的字段值修改前的状态 */
                addInIds_ByDependMatchColValues(upperTableColumnOperation);
                //存到字典
                columnRuleOperationStore.addTableColumnRule(upperTableColumnOperation.tableName, upperTableColumnOperation);
            }
            //更新当前表数据
            for (ColumnRuleOperation m : columnRuleOperationStore.getOperationList(table_name)) {
                if (m.updateType.equals("user-form")) {
                    int rs = baseDBService.updateIn(m.tableName, Lutils.genMap(m.column, m.value), "id_", m.inIds);
                } else if (m.updateType.equals("this-table-express")) {

                } else if (m.updateType.equals("depend-col-new-value")) {
                    int rs = flowableMapper.update_by_depend_col_new_value(m.getMybatisMap());
                } else if (m.updateType.equals("depend-col-count")) {
                    int rs = flowableMapper.update_by_depend_col_count(m.getMybatisMap());
                } else if (m.updateType.equals("depend-col-count-distinct")) {

                }
                m.isColumnUpdated = true;
                //更新完，补充本表格依赖数据
                for (ColumnRuleOperation tmpThisRule : columnRuleOperationStore.getOperationList(table_name)) {
                    if (tmpThisRule.isWhereSupplementByNewValue)
                        continue;
                    //检查关联的列，是否已经更新，如果都更新了，则根据新值，补充ids
                    int relColUpdatedCount = 0;
                    int relColCount = 0;
                    int relFormColCount = 0;
                    for (ColumnRuleOperation tmpRelRule : columnRuleOperationStore.getOperationList(table_name)) {
                        //是关联的值
                        if (tmpThisRule.updateRelation.getDependFields().contains(tmpRelRule.column)) {
                            relColCount++;
                            //如果关联的列还未更新，则结束
                            if (tmpRelRule.isColumnUpdated) {
                                relColUpdatedCount++;
                            }
                            if(tmpRelRule.updateType.equals("user-form")) {
                                relFormColCount ++;
                            }
                        }
                    }
                    //如果该列未补充过,且关联的字段都更新了值,则根据depend表新值,获取当前表的ids
                    if (relColCount == relColUpdatedCount && relColCount > 0) {
                        /** 获取依赖表的Ids，锁定这些ids，用于后期这些ids对应的行，修改前后的值，获取更新表的ids，即依赖更新的范围 */
                        //存在非表单类更新的列，这些列的更新范围，会根据依赖值修改前后变化，所以依赖这些列的上级字段的dependids也会变化，导致上级表的更新范围变化。
                        if(relFormColCount<relColCount)
                            addDependIds_FromDependColumnOperations(tmpThisRule,
                                    columnRuleOperationStore.getOperationList(tmpThisRule.dependTableName));
                        /** 根据Depend表锁定的ids,在Depend表取不同的关联的字段值组合,在新表查询这个组合,获得当前表关联ids行 */
                        addInIds_ByDependMatchColValues(tmpThisRule);
                        tmpThisRule.isWhereSupplementByNewValue = true;
                    }
                }
            }
            //更新UpperTable的更新范围，即inIds
            // 根据变动的列，取触发上级表触发更新的列 ----
            // 先锁定依赖表的ids，根据行信息获取上级表的待更新的ids
            for (TableColumnRelation upperRelation : upperDependRelation) {
                // 创建新规则
                ColumnRuleOperation upperTableColumnOperation = columnRuleOperationStore.getColumnOperation(upperRelation.table_name, upperRelation.update_column);
                /** 获取依赖表的Ids，锁定这些ids，用于后期这些ids对应的行，修改前后的值，获取更新表的ids，即依赖更新的范围 */
                addDependIds_FromDependColumnOperations(upperTableColumnOperation, columnRuleOperationStore.getOperationList(upperTableColumnOperation.dependTableName));
                /** 获取Upper表的inIds，此时匹配的字段值修改前的状态 */
                addInIds_ByDependMatchColValues(upperTableColumnOperation);
            }
            //本级处理好后，删除本级数据 ???
            columnRuleOperationStore.removeTableOperations(table_name);
        }
    }


    public void data_mode_delete(Map userInfo, List ids, String tn){
        //更新time_if_delete数据
        flowableMapper.set_delete_time(MapUtils.G("tn", tn, "ids", ids,
                "action_type_", "data-delete",
                "update_user_", userInfo.get("user_name"),
                "update_group_", userInfo.get("user_group"),
                "update_time_", new Date()));
        //获取新添加的数据，插入日志表
        flowableMapper.copy_to_log(MapUtils.G("tn", tn, "ids", ids, "log_time_", new Date()));
    }


    /**
     * 根据依赖表的ids所在行 关联当前表match_column的值, 与当前表match_column匹配的ids,ids即当前表要依赖更新的范围.
     * @param columnRule  当前列的操作对象ColumnRuleOperation
     * */
    public void addInIds_ByDependMatchColValues(ColumnRuleOperation columnRule){
        List<Map> dependDependFieldOldValues = baseDBService.selectIn(
                columnRule.dependTableName,
                true,
                columnRule.updateRelation.getDependMatchFields(),
                "id_",
                columnRule.dependIds);
        ///------------------------------------------------------------------------
        for (Map dependTableOldRow : dependDependFieldOldValues) {
            Map triggerTableOldMatchValue = new HashMap();
            if(Lutils.nvl(columnRule.updateRelation.match_column1,"").length()>0){
                triggerTableOldMatchValue.put(columnRule.updateRelation.match_column1, dependTableOldRow.get(columnRule.updateRelation.depend_table_match_column1));
            }
            if(Lutils.nvl(columnRule.updateRelation.match_column2,"").length()>0){
                triggerTableOldMatchValue.put(columnRule.updateRelation.match_column2, dependTableOldRow.get(columnRule.updateRelation.depend_table_match_column2));
            }
            if(Lutils.nvl(columnRule.updateRelation.match_column3,"").length()>0){
                triggerTableOldMatchValue.put(columnRule.updateRelation.match_column3, dependTableOldRow.get(columnRule.updateRelation.depend_table_match_column3));
            }
            columnRule.orWhereOfRowsList.add(triggerTableOldMatchValue);
        }
        //查匹配的行的ids
        List<Integer> inIds = baseDBService.selectByCauses(columnRule.tableName,
                Lutils.genList("id_"),
                columnRule.getWhereCause(),
                null).stream().map(o->(Integer)o.get("id_")).collect(Collectors.toList());
        columnRule.addInIds(inIds);
    }

    public void addDependIds_FromDependColumnOperations(ColumnRuleOperation upperTableColumnOperation, List<ColumnRuleOperation> dependTableColOperationList)
    {
        for (String column : upperTableColumnOperation.updateRelation.getDependFields()) {
            //根据每个关联的列，找到匹配的操作，合并操作中的where条件
            for (ColumnRuleOperation dependColumnRuleOperation : dependTableColOperationList) {
                if (column.equals(dependColumnRuleOperation.column)) {
                    upperTableColumnOperation.dependIds.addAll(dependColumnRuleOperation.inIds);
                }
            }
        }
    }
}
